package com.weed.table.scrollpane;

import java.awt.Component;
import javax.swing.*;
import java.util.Vector;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.text.JTextComponent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.awt.BorderLayout;
import javax.swing.text.Document;
import java.beans.*;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.border.Border;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Insets;

/**
 * 函数说明:
 *
 * 支待组件的行头显示。主要支待如下几种Component，JTabel、JTextArea、JTextPane、JEditorPane等
 *
 * 版本    修订人        说明
 * 0.1    Jason Zhuo    新增对组件Component，JTabel、JTextArea、JTextPane、JEditorPane行头显示。
 */

public class JScrollPaneEx
    extends JScrollPane {
  /**扩展的ScrollPane默认的行头显示。*/
  protected JList defaultRowHeader = new JList();
  protected Component view;
  protected Vector vector = new Vector();
  protected Component oldRowHeaderView = null;
  protected JPanel pane = new JPanel();
  /**
   * 行头的样式。
   */
  public static final String STYLE_BUTTON = "TableHeader.cellBorder";
  public static final String STYLE_LABEL = "LabelUI";
//  private FontMetrics metrics ;//行高。
  protected int rowHeight; //行高
  protected Font font;
  protected String style = STYLE_LABEL;
  protected DefaultRowHeaderRenderer defaultRowHeaderRenderernew; //默认行头绘制者。
  //行头使用JTooBar组件。
  protected JToolBar toolbar = new JToolBar();
  protected boolean columnHeaderVisible = true;
  protected Color rightColor = new Color(0, 0, 0);
  protected Color leftColor = new Color(0, 0, 0);
  protected ColumnBorder colBorder = new ColumnBorder();
  protected JLabel label = new JLabel() {
    public Dimension getPreferredSize() {
      Dimension dm = super.getPreferredSize(); ;
      double d = dm.getHeight();
      if (d < 29d)
        dm.setSize(dm.getWidth(), 29d);
      return dm;
    }
  };

  /**
   * 是否显示行头。默认为不显示。
   */
  boolean displayRowHandler = false;
  /**
   * 构造函数1。
   */

  public JScrollPaneEx() {
    super();
    init(null, null);
  }

  /**
   * 构造函数2。
   */

  public JScrollPaneEx(Component view, int vsbPolicy, int hsbPolicy) {
    super(view, vsbPolicy, hsbPolicy);
    init(null, null);
  }

  /**
   * 构造函数3。
   */

  public JScrollPaneEx(Component view) {
    super(view);
    init(null, null);
  }

  /**
   * 构造函数4。
   */

  public JScrollPaneEx(int vsbPolicy, int hsbPolicy) {
    super(vsbPolicy, hsbPolicy);
    init(null, null);
  }

  /**
   * 初始化。
   */
  private void init(Color rightColor, Color leftColor) {
    pane.setLayout(new BorderLayout());
    defaultRowHeader.setBackground(new Color(247, 247, 247));
    defaultRowHeader.setFixedCellWidth(30);
    if (defaultRowHeaderRenderernew == null)
      defaultRowHeaderRenderernew = new DefaultRowHeaderRenderer(style);
    defaultRowHeader.setCellRenderer(defaultRowHeaderRenderernew);
    setRowHeaderView(defaultRowHeader);
    initComponetListener(super.getViewport().getView());
    super.getViewport().addContainerListener(new ContainerAdapter() {
      public void componentAdded(ContainerEvent e) {
        initComponetListener(e.getChild());
      }

      public void componentRemoved(ContainerEvent e) {}
    });
    super.setColumnHeaderView(toolbar);
    if (rightColor != null && leftColor != null)
      colBorder = new ColumnBorder(rightColor, leftColor);
    toolbar.add(label);
    label.setForeground(Color.white);
    label.setFont(new java.awt.Font("Dialog", 0, 13));
    toolbar.setBorder(colBorder);
    toolbar.setFloatable(false);
    label.setPreferredSize(label.getPreferredSize());
  }

  /**
   * 当新增一行时，行头加1.
   */
  protected void initComponetListener(Component view) {
    if (view != null) {
      if (view instanceof JTable) {
        handlerTable(view);
      }
      if (view instanceof JList) {
        handlerList(view);
      }

      if (view instanceof JTextComponent) {
        handlerTextComponent(view);
      }
    }
  }

  public void handlerTable(Component view) {
    FontMetrics metrics = getFontMetrics(view.getFont());
    font = metrics.getFont();
    rowHeight = metrics.getHeight();
    insertMultiRowHeader( ( (JTable) view).getRowCount());
    defaultRowHeader.setFixedCellHeight( ( (JTable) view).getRowHeight());
    ( (JTable) view).addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if (e.getNewValue() instanceof TableModel) {
          int rowCount = ( (TableModel) e.getNewValue()).getRowCount();
          JTable table = ( (JTable) e.getSource());
          for (int i = 0; i < rowCount; i++) {
            insertRowHeader(table.getRowHeight(i), font);
          }
        }
      }
    });

    ( (JTable) view).getModel().addTableModelListener(new TableModelListener() {
      public void tableChanged(TableModelEvent e) {
        if (e.getType() == TableModelEvent.INSERT)
          insertRowHeader();
        if (e.getType() == TableModelEvent.DELETE)
          removeRowHeader();
      }
    });
  }

  /**
   * 添加的内容为JList.
   */
  private void handlerList(Component view) {
    JList list = (JList) view;
    FontMetrics metrics = getFontMetrics(view.getFont());
    font = metrics.getFont();
    rowHeight = metrics.getHeight();
    defaultRowHeader.setFixedCellHeight(list.getFixedCellHeight());
    insertMultiRowHeader(list.getModel().getSize());
    defaultRowHeader.setFont(list.getFont());
    list.getModel().addListDataListener(new ListDataListener() {
      public void intervalAdded(ListDataEvent e) {
        if ( ( (JList) e.getSource()).getModel().getSize() >= getRowHeaderSize()) {
          insertMultiRowHeader( ( ( (JList) e.getSource()).getModel().getSize() -
                                 getRowHeaderSize()));
        }
      }

      public void intervalRemoved(ListDataEvent e) {
        if ( ( (JList) e.getSource()).getModel().getSize() <= getRowHeaderSize()) {
          removeRowHeader(getRowHeaderSize() -
                          ( ( (JList) e.getSource()).getModel().getSize()));
        }
      }

      public void contentsChanged(ListDataEvent e) {
        if ( ( (JList) e.getSource()).getModel().getSize() >= getRowHeaderSize()) {
          insertMultiRowHeader( ( ( (JList) e.getSource()).getModel().getSize() -
                                 getRowHeaderSize()));
        }
        else {
          removeRowHeader(getRowHeaderSize() -
                          ( ( (JList) e.getSource()).getModel().getSize()));
        }
      }
    });
    list.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if (e.getPropertyName().equals("model")) {
          if ( ( (JList) e.getSource()).getModel().getSize() >=
              getRowHeaderSize()) {
            insertMultiRowHeader( ( ( (JList) e.getSource()).getModel().getSize() -
                                   getRowHeaderSize()));
          }
          else {
            removeRowHeader(getRowHeaderSize() -
                            ( ( (JList) e.getSource()).getModel().getSize()));
          }
        }
        if (e.getPropertyName().equals("font")) {
          defaultRowHeader.setFont( ( (JList) e.getSource()).getFont());
          defaultRowHeader.setFixedCellHeight( ( (JList) e.getSource()).
                                              getFixedCellHeight());
        }
      }
    });

  }

  /**
   * 添加的内容为JTextComponent
   */

  private void handlerTextComponent(Component view) {
    Document doc = ( (JTextComponent) view).getDocument();
    FontMetrics metrics = getFontMetrics(view.getFont());
    font = metrics.getFont();
    rowHeight = metrics.getHeight();
    insertMultiRowHeader(doc.getDefaultRootElement().getElementCount());
    ( (JTextComponent) view).getDocument().addDocumentListener(new
        DocumentListener() {
      public void insertUpdate(DocumentEvent e) {
        if (getRowHeaderSize() <
            e.getDocument().getDefaultRootElement().getElementCount()) {
          insertRowHeader(rowHeight, font,
                          e.getDocument().getDefaultRootElement().
                          getElementCount() - getRowHeaderSize());
        }
      }

      public void removeUpdate(DocumentEvent e) {
        if (getRowHeaderSize() >
            e.getDocument().getDefaultRootElement().getElementCount()) {
          removeRowHeader(getRowHeaderSize() -
                          e.getDocument().getDefaultRootElement().
                          getElementCount());
        }
      }

      public void changedUpdate(DocumentEvent e) {
      }
    });

  }

  /**
   * 在行头中插入多行。
   */
  public void insertMultiRowHeader(int rowCount) {
    for (int i = 0; i < rowCount; i++) {
      insertRowHeader();
    }
  }

  public void insertMultiRowHeader(int rowCount, Component view) {
    if (view instanceof JTable) {
      JTable table = ( (JTable) view);
      for (int i = 0; i < rowCount; i++) {
        insertRowHeader(table.getRowHeight(i), table.getFont());
      }
    }
  }

  /**
   * 设置行头是否显示。
   * @param displayRowHandler true = 显示  false = 不显示
   */
  public void setDisplayRowHeader(boolean displayRowHandler) {
    this.displayRowHandler = displayRowHandler;
    if (!displayRowHandler) {
      oldRowHeaderView = getRowHeaderView();
      super.setRowHeaderView(null);
    }
    else {
      if (oldRowHeaderView != null) {
        super.setRowHeaderView(oldRowHeaderView);
      }
      else {
        super.setRowHeaderView(defaultRowHeader);
      }
    }
  }

  /**
   * 设置行头显示的控件。
   */
  public void setRowHeaderView(Component view) {
    if (view != null) {
      this.view = view;
      if (view.equals(defaultRowHeader)) {
        pane.add(view, BorderLayout.WEST);
      }
      else {
        pane.add(view, BorderLayout.CENTER);
      }
      super.setRowHeaderView(pane);
    }
  }

  public Component getRowHeaderView() {
    return view;
  }

  /**
   * 返回行头是否允许显示。
   * @return true = 允许显示  false = 不允许
   */
  public boolean getDisplayRowHeader() {
    return displayRowHandler;
  }

  /**
   * 行头显示绘制对象。
   * @return
   */
  public Component getDefaultRowHeaderRenderer() {
    return rowHeader;
  }

  /**
   * 添加一个行头。
   * @param item
   */
  public void insertRowHeader(Object item) {
    if (item == null) {
      vector.addElement("");
    }
    else {
      vector.addElement(item.toString());
    }
    defaultRowHeader.setListData(vector);
  }

  /**
   * 添加一个行头。
   */

  public void insertRowHeader() {
    vector.addElement("");
    defaultRowHeader.setListData(vector);
  }

  /**
   * 插入行号同时设置行高度。
   */
  public void insertRowHeader(int height, Font font) {
    defaultRowHeader.setFixedCellHeight(height);
    if (defaultRowHeaderRenderernew != null)
      defaultRowHeaderRenderernew.setFont(font);
    vector.addElement("");
    defaultRowHeader.setListData(vector);
  }

  public void insertRowHeader(int height, Font font, int multi) {
    defaultRowHeader.setFixedCellHeight(height);
    if (defaultRowHeaderRenderernew != null)
      defaultRowHeaderRenderernew.setFont(font);
    for (int i = 0; i < multi; i++) {
      vector.addElement("");
    }
    defaultRowHeader.setListData(vector);
  }

  /**
   * 移除一个行头。
   */

  public void removeRowHeader() {
    vector.removeElementAt(vector.size() - 1);
    defaultRowHeader.setListData(vector);
  }

  /**
   * 移除多个行头。
   */
  public void removeRowHeader(int multi) {
    int m = multi;
    if (vector.size() < multi)
      m = vector.size();
    for (int i = 0; i < m; i++) {
      vector.removeElementAt(0);
    }
    defaultRowHeader.setListData(vector);
  }

  /**
   * 获得行头的数量。
   */
  public int getRowHeaderSize() {
    return vector == null ? 0 : vector.size();
  }

  /**
   * 设置行头的显示的样式。目前只支待两种为STYLE_BUTTON ,STYLE_LABEL
   */
  public void setStyle(String style) {
    if (style != null) {
      this.style = style;
      defaultRowHeaderRenderernew = new DefaultRowHeaderRenderer(style);
      defaultRowHeader.setCellRenderer(defaultRowHeaderRenderernew);
    }
  }

  /**
   * 获得当前显示行头的样式。
   */
  public String getStyle() {
    return style;
  }

  /**设置列头的文本。*/
  public void setHeaderText(String text) {
    label.setText(text);
  }

  /**获得列头的文本。*/
  public String getHeaderText() {
    return label.getText();
  }

  /**设置列头的图标。*/
  public void setHeaderIcon(Icon icon) {
    if (icon != null && icon.getIconHeight() > 0)
      label.setIcon(icon);
  }

  /**获得列头的图标。*/
  public Icon getHeaderIcon() {
    return label.getIcon();
  }

  /**设置是否显示列头。*/
  public void setColumnHeaderVisible(boolean columnHeaderVisible) {
    toolbar.setVisible(columnHeaderVisible);
  }

  /**获得当前列头的显示状态。*/
  public boolean getColumnHeaderVisible() {
    return toolbar.isVisible();
  }

  /**设置列头的Border.*/
  public void setColumnHeaderBorder(Border border) {
    toolbar.setBorder(border);
  }

  /**获得列头的Border.*/
  public Border getColumnHeaderBorder() {
    return toolbar.getBorder();
  }
}

class ColumnBorder
    implements Border {

  protected int thickness = 1;
  protected Color rightColor = new Color(66, 113, 189),
  leftColor = new Color(231, 231, 214);
  protected Color fimColor = new Color(181, 182, 165);
  /**构造函数1.*/
  public ColumnBorder() {}

  /**构造函数2.*/
  public ColumnBorder(Color rightColor, Color leftColor) {
    this.rightColor = rightColor;
    this.leftColor = leftColor;
  }

  public void paintBorder(Component c, Graphics g, int x, int y, int width,
                          int height) {
    Color oldColor = g.getColor();
    int i;
    g.setColor(fimColor);
//    SwingUtil.drawGradient(g, rightColor, leftColor,
//                           new Rectangle(0, y, width - 1, 30), false);
//    SwingUtil.drawSpecyRect(g, Color.white, fimColor,
//                            new Rectangle(x, y, width, height));
    g.setColor(oldColor);
 }

  public Insets getBorderInsets(Component c) {
    return new Insets(thickness, thickness, thickness, thickness);
  }

  public boolean isBorderOpaque() {
    return true;
  }

  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception e) {
    }

    JFrame frame = new JFrame();
    JTextArea jta = new JTextArea("1234");
    jta.setFont(new java.awt.Font("Dialog", 0, 24));
    JScrollPaneEx jsp = new JScrollPaneEx(new JTable(3,3));
    jsp.setStyle(JScrollPaneEx.STYLE_BUTTON);

    //EXIT_ON_CLOSE == 3
    frame.setDefaultCloseOperation(3);
    frame.setTitle("JStatusBar Demo");
    jsp.setColumnHeaderVisible(true);
//    jsp.setHeaderText("我的中国心!");
//    frame.getContentPane().add(spe, BorderLayout.SOUTH);
    frame.getContentPane().add(jsp,
                               BorderLayout.CENTER);
    frame.setSize(400, 320);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    frame.setLocation( (d.width - frame.getSize().width) / 2,
                      (d.height - frame.getSize().height) / 2);
    frame.setVisible(true);
  }

}

class ExitAction
    extends AbstractAction {
  public ExitAction() {}

  public void actionPerformed(ActionEvent e) {

  }
}

/**
 * 默认的行头显示。
 */
class DefaultRowHeaderRenderer
    extends JLabel implements ListCellRenderer {

  public DefaultRowHeaderRenderer(String style) {
    setOpaque(true);
//    setFont(new java.awt.Font("Dialog", 0, 14));
    if (style.equals(JScrollPaneEx.STYLE_BUTTON)) {
      setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      setForeground(getForeground());
      setBackground(getBackground());
    }
    else {
      setBackground(new Color(247, 247, 247));
      setForeground(new Color(156, 154, 206));
    }
    setHorizontalAlignment(CENTER);

  }

  /**获得行头的绘制者。*/
  public Component getListCellRendererComponent(
      JList list,
      Object value,
      int index,
      boolean isSelected,
      boolean cellHasFocus) {
    if (value != null && !value.equals("")) {
      setText(value.toString());
    }
    else {
      setText("" + (index + 1)); //索引从1开始。
    }
    return this;
  }
}

